#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
统一任务API
提供录制、转码、转推的任务管理接口
集成任务队列系统
"""

from fastapi import APIRouter, HTTPException, Depends, Query
from pydantic import BaseModel, Field
from typing import List, Optional, Dict, Any
from datetime import datetime
import json

from app.services.task_service import get_task_service
from app.services.task_queue_manager import get_task_queue
from app.core.database import SessionLocal
from app.models.task import Task, TaskStatus
from app.models.stream import Stream

router = APIRouter()

# 初始化服务
# 使用单例模式获取服务实例
task_service = get_task_service()

# 请求模型
class CreateTaskRequest(BaseModel):
    name: str = Field(..., description="任务名称")
    task_type: str = Field(..., description="任务类型: record, push, transcode, clip 或它们的组合，如 record_transcode_push")
    stream_id: int = Field(..., description="关联流ID")
    record_path: Optional[str] = Field(None, description="录制文件路径，录制任务时必填")
    push_url: Optional[str] = Field(None, description="转推地址，转推任务时必填")
    tempid: Optional[str] = Field(None, description="转码模板ID，转码任务时必填")
    transcode_url: Optional[str] = Field(None, description="转码输出地址，格式为rtmp地址;url地址，转码任务时必填")
    max_retries: Optional[int] = Field(3, description="最大重试次数")

class TaskResponse(BaseModel):
    id: int
    name: str
    task_type: str
    status: str
    stream_id: int
    stream_name: Optional[str] = None
    config: Dict[str, Any]
    record_path: Optional[str]
    record_duration: Optional[int]
    segment_duration: int
    push_url: Optional[str]
    tempid: Optional[str]
    transcode_url: Optional[str]
    output_path: Optional[str]
    pid: Optional[int]
    progress: int
    error_message: Optional[str]
    retry_count: int
    max_retries: int
    created_at: str
    started_at: Optional[str]
    completed_at: Optional[str]
    updated_at: Optional[str]

class TaskListResponse(BaseModel):
    total: int
    items: List[TaskResponse]

@router.post("/create", response_model=Dict[str, Any])
async def create_task(request: CreateTaskRequest):
    """创建任务并加入队列"""
    print("/create",request)
    try:
        # 验证任务类型 - 允许任意组合
        valid_single_types = ["record", "push", "transcode", "clip"]
        task_types = request.task_type.split('_')
        
        for task_type in task_types:
            if task_type not in valid_single_types:
                raise HTTPException(status_code=400, detail=f"任务类型包含无效值: {task_type}，支持: {', '.join(valid_single_types)}")
        print("task_types",task_types)
        # 验证必填参数
        if "record" in task_types and not request.record_path:
            raise HTTPException(status_code=400, detail="录制任务需要提供record_path参数")
        if "push" in task_types and not request.push_url:
            raise HTTPException(status_code=400, detail="转推任务需要提供push_url参数")
        if "transcode" in task_types and not request.tempid:
            raise HTTPException(status_code=400, detail="转码任务需要提供tempid参数")
        if "transcode" in task_types and not request.transcode_url:
            raise HTTPException(status_code=400, detail="转码任务需要提供transcode_url参数，格式为rtmp地址;url地址")       
        
        # 将所有数据库操作放在同一个会话中
        with SessionLocal() as db:
            # 验证流存在
            stream = db.query(Stream).filter(Stream.id == request.stream_id).first()
            if not stream:
                raise HTTPException(status_code=404, detail="关联流不存在")
            stream_name = stream.name
            print("stream_name",stream_name)
            
            # 检查录制任务 - 如果已存在录制任务，从任务类型中移除       
            if "record" in task_types:
                existing_record_task = db.query(Task).filter(
                    Task.stream_id == request.stream_id,
                    Task.task_type.contains("record"),
                    Task.inuse == 1
                ).first()
                print("existing_record_task",existing_record_task)
                if existing_record_task:
                    # 移除录制相关配置
                    task_types = [t for t in task_types if t != "record"]
                    request.record_path = None
                    
                    # 如果没有其他任务了，直接返回
                    if not task_types:
                        return {
                            "code": 200,
                            "message": "录制任务已存在，无其他任务需要创建",
                            "data":{
                                "task_id": existing_record_task.id                             
                            }                                
                        }
            
            # 构建任务数据 - 使用修改后的task_types
            final_task_type = '_'.join(task_types) if task_types else request.task_type
            print("final_task_type",final_task_type)
            task_data = {
                "name": request.name,
                "task_type": final_task_type,
                "stream_id": request.stream_id,
                "record_path": request.record_path,
                "push_url": request.push_url,
                "tempid": request.tempid,
                "transcode_url": request.transcode_url,
                "max_retries": request.max_retries
            }
            print("create task ",task_data)
            
            # 使用任务服务创建任务并加入队列
            result = await task_service.create_task_with_queue(task_data)
            print("create task result",result)
            
            # 更新streams表中对应的任务计数字段
            stream = db.query(Stream).filter(Stream.id == request.stream_id).first()
            print("stream",stream)
            if stream:
                if "record" in task_types:
                    stream.is_recording = 1  # 录制任务只能有一个
                if "transcode" in task_types:
                    stream.is_transcode = (stream.is_transcode or 0) + 1
                if "push" in task_types:
                    stream.is_pushing = (stream.is_pushing or 0) + 1
                
                db.commit()
        
        # 检查返回结果中是单个task_id还是多个task_ids
        if "task_id" in result:
            return {            
                "code": 200,
                "message": "创建任务成功",
                "data": {
                    "task_id": result["task_id"],
                    "status": result["status"],
                    "message": result["message"]
                }
            }
        else:
            return {            
                "code": 200,
                "message": "创建任务成功",
                "data": {
                    "task_ids": result["task_ids"],
                    "status": result["status"],
                    "message": result["message"]
                }
            }
        
    except Exception as e:
        print(f"创建任务失败: {e}")
        raise HTTPException(status_code=500, detail=str(e))


@router.get("/list")
async def list_tasks(
    status: Optional[str] = Query(None, description="任务状态"),
    task_type: Optional[str] = Query(None, description="任务类型"),
    stream_id: Optional[int] = Query(None, description="关联流ID"),
    page: int = Query(1, ge=1, description="页码"),
    limit: int = Query(20, ge=1, le=100, description="每页数量")
):
    """任务列表查询 - 统一返回格式"""
    try:
        with SessionLocal() as db:
            query = db.query(Task).filter(Task.inuse == 1)
            
            # 应用筛选条件
            if status:
                query = query.filter(Task.status == TaskStatus(status))
            if task_type:
                query = query.filter(Task.task_type == task_type)
            if stream_id:
                query = query.filter(Task.stream_id == stream_id)
            
            # 计算总数
            total = query.count()
            
            # 分页查询
            tasks = query.order_by(Task.created_at.desc()).offset((page - 1) * limit).limit(limit).all()
            
            # 构建响应 - 统一格式
            items = []
            for task in tasks:
                # 获取流名称
                stream = db.query(Stream).filter(Stream.id == task.stream_id).first()
                stream_name = stream.name if stream else None
                
                items.append({
                    "id": task.id,
                    "name": task.name,
                    "task_type": task.task_type,
                    "status": task.status.value,
                    "stream_id": task.stream_id,
                    "stream_name": stream_name,
                    "record_path": task.record_path,  
                    "push_url": task.push_url,
                    "tempid": task.tempid,
                    "transcode_url": task.transcode_url,
                    "output_path": task.output_path,
                    "pid": task.pid,
                    "progress": task.progress,
                    "error_message": task.error_message,
                    "file_size": task.file_size,
                    "retry_count": task.retry_count,
                    "max_retries": task.max_retries,
                    "created_at": task.created_at.isoformat(),
                    "started_at": task.started_at.isoformat() if task.started_at else None,
                    "completed_at": task.completed_at.isoformat() if task.completed_at else None,
                    "updated_at": task.updated_at.isoformat() if task.updated_at else None
                })
            
            return {
                "code": 200,
                "data": {
                    "items": items,
                    "total": total
                },
                "message": "success"
            }
            
    except Exception as e:
        return {
            "code": 500,
            "data": None,
            "message": str(e)
        }

@router.get("/{task_id}")
async def get_task(task_id: int):
    """获取单个任务详情"""
    try:
        with SessionLocal() as db:
            task = db.query(Task).filter(Task.id == task_id, Task.inuse == 1).first()
            if not task:
                raise HTTPException(status_code=404, detail="任务不存在")
            
            # 获取流名称
            stream = db.query(Stream).filter(Stream.id == task.stream_id).first()
            stream_name = stream.name if stream else None
            
            return {
                "code": 200,
                "message": "success",
                "data": {
                    "id": task.id,
                    "name": task.name,
                    "task_type": task.task_type,
                    "status": task.status.value,
                    "stream_id": task.stream_id,
                    "stream_name": stream_name,
                    "record_duration": task.record_duration,
                    "segment_duration": task.segment_duration,
                    "push_url": task.push_url,
                    "push_key": task.push_key,
                    "output_path": task.output_path,
                    "pid": task.pid,
                    "progress": task.progress,
                    "error_message": task.error_message,
                    "retry_count": task.retry_count,
                    "max_retries": task.max_retries,
                    "created_at": task.created_at.isoformat(),
                    "started_at": task.started_at.isoformat() if task.started_at else None,
                    "completed_at": task.completed_at.isoformat() if task.completed_at else None,
                    "updated_at": task.updated_at.isoformat() if task.updated_at else None
                }
            }
            
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))

@router.post("/{task_id}/start")
async def start_task(task_id: int):
    """手动启动任务（将失败或取消的任务重新加入队列）"""
    try:
        with SessionLocal() as db:
            task = db.query(Task).filter(Task.id == task_id, Task.inuse == 1).first()
            if not task:
                raise HTTPException(status_code=404, detail="任务不存在")
            
            # 只有失败或取消的任务可以重新启动
            if task.status not in [TaskStatus.FAILED, TaskStatus.CANCELLED]:
                raise HTTPException(status_code=400, detail="只有失败或取消的任务可以重新启动")
            
            task.status = TaskStatus.PENDING
            task.error_message = None
            task.pid = None
            db.commit()
            
            return {"success": True, "message": "任务已重新加入队列"}
            
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))

@router.post("/{task_id}/stop")
async def stop_task(task_id: int):
    """停止任务"""
    try:
        with SessionLocal() as db:
            task = db.query(Task).filter(Task.id == task_id, Task.inuse == 1).first()
            if not task:
                raise HTTPException(status_code=404, detail="任务不存在")
            
            # 只有运行中的任务可以停止
            if task.status != TaskStatus.RUNNING:
                raise HTTPException(status_code=400, detail="任务未在运行中")
            
            # 通过任务队列停止任务
            queue = get_task_queue()
            await queue._stop_task(task_id)
            
            return {"success": True, "message": "任务已停止"}
            
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))

@router.post("/{task_id}/retry")
async def retry_task(task_id: int):
    """重试失败的任务"""
    try:
        result = await task_service.retry_failed_task(task_id)
        if result:
            return {"success": True, "message": "任务已加入重试队列"}
        else:
            raise HTTPException(status_code=400, detail="任务已达到最大重试次数")
            
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))

@router.delete("/{task_id}")
async def delete_task(task_id: int):
    """删除任务（软删除）"""
    try:
        with SessionLocal() as db:
            task = db.query(Task).filter(Task.id == task_id, Task.inuse == 1).first()
            if not task:
                raise HTTPException(status_code=404, detail="任务不存在")
            
            # 如果任务正在运行，先停止
            if task.status == TaskStatus.RUNNING:
                manager = get_task_queue()
                await manager._stop_task(task_id)
            
            # 更新streams表中对应的任务计数字段
            stream = db.query(Stream).filter(Stream.id == task.stream_id).first()
            if stream:
                task_types = task.task_type.split('_')
                if "record" in task_types:
                    stream.is_recording = 0  # 录制任务只能有一个
                if "transcode" in task_types:
                    stream.is_transcode = max(0, (stream.is_transcode or 0) - 1)
                if "push" in task_types:
                    stream.is_pushing = max(0, (stream.is_pushing or 0) - 1)
            
            # 软删除
            task.inuse = 0
            db.commit()
            
            return {"success": True, "message": "任务已删除"}
            
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))

@router.get("/stats/summary")
async def get_task_stats():
    """获取任务统计信息"""
    try:
        with SessionLocal() as db:
            stats = {
                "total": db.query(Task).filter(Task.inuse == 1).count(),
                "pending": db.query(Task).filter(Task.status == TaskStatus.PENDING, Task.inuse == 1).count(),
                "running": db.query(Task).filter(Task.status == TaskStatus.RUNNING, Task.inuse == 1).count(),
                "completed": db.query(Task).filter(Task.status == TaskStatus.COMPLETED, Task.inuse == 1).count(),
                "failed": db.query(Task).filter(Task.status == TaskStatus.FAILED, Task.inuse == 1).count(),
                "cancelled": db.query(Task).filter(Task.status == TaskStatus.CANCELLED, Task.inuse == 1).count()
            }
            
            return {"success": True, "data": stats}
            
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))